package main

import (
	"fmt"
)

//数组的个数不确定时，可以使用切片；
//切片是引用类型！切片的长度是可以变化的！
//var slice []int  []内不需要写长度 ;;slice由三个部分组成，1切片首地址，2切片长度，3切片容量 。切片可以看出struct结构体的数据结构！！！！
//切片的使用！
func main() {

	var array = [...]int{1, 2, 3, 4, 5, 1, 2, 3, 4, 5}
	//切片slice引用了array数组的下标的[1，3)的
	slice := array[1:6]
	//输出看看
	fmt.Println("原数组：", array)
	fmt.Printf("切片：%p====%p\n", &slice[0], &array[1])
	//cap（）内置函数，说明该切片容量；具体容量就是切片下标[1-原数组长度差]，比如10个元素，切片[2,4]，容量就是（10-2）8，切片[5,9]容量就是（10-5）5
	fmt.Println("切片容量：", cap(slice))

	//创建切片方式2：  通过内置函数make(type,len,[cap])创建   ,容量可选不填 --------------------------------------------
	var slice2 []int = make([]int, 4, 10)
	//创建完切片只能通过切片去访问不可见的数组，无法用对应数组去访问，并且切片首地址指向新建数组的首元素地址，初始化元素均为0
	fmt.Println("切片2：", slice2)

	//创建切片方式3：------------------------------------------------------------------
	var slice3 []int = []int{1, 2, 3, 4, 5}
	fmt.Println("切片2：", slice3)
	fmt.Println("切片2 大小：", len(slice3))
	fmt.Println("切片2 容量：", cap(slice3))

	//切片的遍历：
	for i := 0; i < len(slice); i++ {
		fmt.Printf("%d - ", slice[i])
	}
	for index, value := range slice3 {
		fmt.Printf("%d:%v\n", index, value)
	}
	fmt.Println()
	fmt.Println()
	//简写切片  取数组的从头到尾的话可写成 var slice = array[:]
	slice4 := array[:]
	for index, value := range slice4 {
		fmt.Printf("%d:%v\n", index, value)
	}

	//切片可继续切片！指向的数据空间是同一块！！！

	//append()内置函数，可以对切片进行动态增长！ 原理：go底层会创建新的所需大小的数组，扩容后将原数据拷贝到新数组在重新指向该数组
	var slice5 []int = []int{100, 200, 300}
	fmt.Println(slice5)
	//通过append()直接追加元素 , 但需要重新赋给原切片
	slice5 = append(slice5, 400, 500)
	fmt.Println(slice5)
	//可以通过append()追加一个切片
	slice5 = append(slice5, slice5...) //需要有3个点
	fmt.Println(slice5)

	//copy()切片的拷贝  //拷贝目标对象无论比被拷贝对象大还是小都能正常拷贝对应的元素
	copy(slice, slice2) //必须都是切片才行
	fmt.Println(slice)

	//string 与 slice  由于string底层是一个byte数组，所以可以进行切片 但是不可以通过slice[0]='s'修改字符串，因为string是不可变的！
	str := "hello@fmx.com"
	slice6 := str[6:] //取str中的第七个元素到结尾所有 slice6仍然是string
	fmt.Printf("======%v--%T \n", slice6, slice6)

	//通过切片修改字符串！  string -> []byte 或 string -> []rune 修改完后在重新 ->string
	byteslice := []byte(str)
	byteslice[0] = 'A'
	str = string(byteslice)
	fmt.Println("str : ", str)
	//若要换成中文的字符，则用[]rune 来处理！
	byteslice2 := []rune(str)
	byteslice2[0] = '爱'
	str = string(byteslice2)
	fmt.Println("str : ", str)

	var array2 = []int{1, 2, 3, 4, 5}
	intslice := []int(array2)
	fmt.Println("intslice : ", intslice)
	fmt.Println()

	//练习：斐波那契数列
	fbnslice := fbn(10)
	fmt.Println(fbnslice)
}
func fbn(n int) []uint {
	fbnslice := make([]uint, n)
	fbnslice[0] = 1
	fbnslice[1] = 1
	for i := 2; i < n; i++ {
		fbnslice[i] = fbnslice[i-1] + fbnslice[i-2]
	}
	return fbnslice
}
